Promise.race = function (args) {
  return new Promise((resolve, reject) => {
    for (let i = 0, len = args.length; i < len; i++) {
      args[i].then(resolve, reject);
    }
  });
};

function debounce(fn, wait) {
  let timer = null;
  return function () {
    let context = this,
      args = arguments;
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, wait);
  };
}

function throttle(fn, delay) {
  let curTime = Date.now();
  return function () {
    let context = this,
      args = arguments,
      nowTime = Date.now();
    if (nowTime - curTime >= delay) {
      curTime = Date.now();
      return fn.apply(context, args);
    }
  };
}

function getType(value) {
  if (value === null) {
    return value + "";
  }
  if (typeof value === "object") {
    let valueClass = Object.prototype.toString.call(value);
    let type = valueClass.slice(8, valueClass.length - 1);
    return type.toLowerCase();
    //.toString().toLowerCase()
  } else {
    return typeof value;
  }
}
// function aa(){}
// console.log(getType(/^1[3456789]\d{9}$/));
// console.log(getType(aa))
// console.log(getType(Symbol('mySymbol')))
// console.log(getType(null))
// console.log(getType(undefined))


Function.prototype.myCall=function(context){
  if(typeof this !=='function'){
    console.log('type error')
  }
  let args=[...arguments].slice(1)
  let result=null;
  context= context || window
  context.fn=this
  result=context.fn(...args)
  delete context.fn
  return result
}

Function.prototype.myApply=function(context){
  if(typeof this !=='function'){
    console.log('type error')
  }
  let result=null;
  context= context || window
  context.fn=this
  if(arguments[1]){
    result=context.fn(...arguments[1])
  }else{
    result=context.fn()
  }
  delete context.fn
  return result
}

Function.prototype.myBind=function(context){
  if(typeof this !=='function'){
    console.log('type error')
  }
  let args=[...arguments].slice(1)
  let fn=this;
  return function Fn(){
    return fn.apply(
      this instanceof Fn ? this :context,
      args.concat(...arguments)
    )
  }
}

function curry(fn,args){
  let length=fn.length;
  args=args || []
  return function(){
    let subArgs=args.slice(0);
    for(let i=0;i<arguments.length;i++){
      subArgs.push(arguments[i])
    }
    if(subArgs.length>length){
      return fn.apply(this,subArgs)
    }else{
      return curry.call(this,fn,args)
    }
  }
}

function curry1(fn,...args){
  return fn.length<=args.length ? fn(...args) :curry.bind(null,fn,...args)
}